﻿using System;

namespace Pfz.Serialization.BinaryBuiltIn
{
	/// <summary>
	/// Serializes any enum type as its underlying type.
	/// </summary>
	/// <typeparam name="T">The type of an Enum to serialize.</typeparam>
	public sealed class EnumSerializer<T>:
		ItemSerializer<T>
	{
		private static readonly Type _itemType;

		/// <summary>
		/// Validates if T is an enum.
		/// </summary>
		static EnumSerializer()
		{
			if (!typeof(T).IsEnum)
				throw new ArgumentException(typeof(T).FullName + " is not an enum.");

			_itemType = Enum.GetUnderlyingType(typeof(T));
		}

		/// <summary>
		/// Gets the singleton instance used to serialize or deserialize the enum values.
		/// </summary>
		public static readonly EnumSerializer<T> Instance = new EnumSerializer<T>();

		private EnumSerializer()
		{
		}

		/// <summary>
		/// Serializes the given enum.
		/// </summary>
		public override void Serialize(ConfigurableSerializerBase serializer, T item)
		{
			var realValue = Convert.ChangeType(item, _itemType);
			serializer.InnerSerialize(realValue, _itemType);
		}

		/// <summary>
		/// Deserializes an enum value.
		/// </summary>
		public override T Deserialize(ConfigurableSerializerBase deserializer)
		{
			var innerValue = deserializer.InnerDeserialize(_itemType);
			var realValue = Enum.ToObject(typeof(T), innerValue);
			return (T)realValue;
		}
	}
}
